package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.BaseException;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.OrederDetailMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.mapper.UserMapper;
import com.sky.properties.BaiduProperties;
import com.sky.result.PageResult;
import com.sky.service.AddressBookService;
import com.sky.service.OrderService;
import com.sky.service.ShoppingCartService;
import com.sky.utils.HttpClientUtil;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.*;
import com.sky.websocket.WebSocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import springfox.documentation.spring.web.json.Json;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 类描述：
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private BaiduProperties baiduProperties;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private AddressBookService addressBookService;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;

    @Autowired
    private OrederDetailMapper orederDetailMapper;

    @Autowired
    private ShoppingCartService shoppingCartService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    @Autowired
    private WebSocketServer webSocketServer;

    @Transactional
    @Override
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
        //1.判断用户地址是否为空，如果为空则抛出异常，结束方法
        Long addressBookId = ordersSubmitDTO.getAddressBookId();
        if (addressBookId == null) {
            throw new OrderBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        //todo  2.判断用户地址距离商家的距离是否超过10公里，如果超过则抛出异常，结束方法
        //2.1获取商家地址经纬度
        //2.1.1封装参数
        HashMap<String, String> adminMap = new HashMap<>();
        adminMap.put("address", baiduProperties.getAddress());
        adminMap.put("ak", baiduProperties.getAk());
        adminMap.put("output", "json");
        //2.1.2调用接口，获取json字符串结果
        String jsonString = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3/?", adminMap);
        JSONObject jsonObject = JSON.parseObject(jsonString); //把json字符串转为json对象
        //2.1.2从 "jsonObject" 中获取 "result" 对应的JSON对象
        JSONObject resultObj = jsonObject.getJSONObject("result");
        // 2.1.3 再从 "result" 对象中获取 "location" 对应的JSON对象
        JSONObject locationObj = resultObj.getJSONObject("location");
        // 2.1.4 现在，从 "location" 对象中获取经纬度
        Double lng = locationObj.getDouble("lng");
        Double lat = locationObj.getDouble("lat");


        //2.2获取用户地址经纬度
        //2.2.1组装用户地址
        AddressBook userAddressBook = addressBookService.getAddressBookById(addressBookId);
        String userAddress = userAddressBook.getProvinceName() + userAddressBook.getCityName() + userAddressBook.getDistrictName() + userAddressBook.getDetail();
        //2.2.2封装参数
        HashMap<String, String> userMap = new HashMap<>();
        userMap.put("address", userAddress);
        userMap.put("ak", baiduProperties.getAk());
        userMap.put("output", "json");
        //2.2.3调用接口
        String userJsonString = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3/?", userMap);
        JSONObject userJsonObject = JSON.parseObject(userJsonString); //把json字符串转为json对象
        //2.2.4从 "jsonObject" 中获取 "result" 对应的JSON对象
        JSONObject userResultObj = userJsonObject.getJSONObject("result");
        // 2.2.5 再从 "result" 对象中获取 "location" 对应的JSON对象
        JSONObject userLocationObj = userResultObj.getJSONObject("location");
        //2.2.6 现在，从 "location" 对象中获取经纬度
        Double userLng = userLocationObj.getDouble("lng");
        Double userLat = userLocationObj.getDouble("lat");

        //2.3 计算距离
        HashMap<String, String> map3 = new HashMap<>();
        map3.put("ak", baiduProperties.getAk());
        //将lng转化为只保留6位小数
        map3.put("origin", String.format("%.6f", lat) + "," + String.format("%.6f", lng));
        map3.put("destination", String.format("%.6f", userLat) + "," + String.format("%.6f", userLng));

        String distanceJsonString = HttpClientUtil.doGet("https://api.map.baidu.com/directionlite/v1/riding?", map3);
        JSONObject distanceJsonObject = JSON.parseObject(distanceJsonString);
        Integer distance=distanceJsonObject
                .getJSONObject("result")
                .getJSONArray("routes")
                .getJSONObject(0)
                .getInteger("distance");
        if (distance > 5000) {
            throw new OrderBusinessException(MessageConstant.TOO_FAR_AWAY);
        }

        //3.补全属性，调用mapper将数据加入oredr订单表
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setUserId(BaseContext.getCurrentId());
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);
        AddressBook addressBook = addressBookService.getAddressBookById(addressBookId);
        orders.setPhone(addressBook.getPhone());
        orders.setAddress(addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail());
        orders.setConsignee(addressBook.getConsignee());
        orderMapper.saveOrder(orders);
        //4.拿到上一步订单表中的订单id（通过options注解），再调用mapper将数据加入order_detail表
        Long orderId = orders.getId();
        ShoppingCart shoppingCart = new ShoppingCart();
        shoppingCart.setUserId(BaseContext.getCurrentId());
        List<ShoppingCart> shoppingCarts = shoppingCartMapper.getShoppingCart(shoppingCart);
        ArrayList<OrderDetail> orderDetails = new ArrayList<>();
        for (ShoppingCart cart : shoppingCarts) {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            BeanUtils.copyProperties(cart, orderDetail);
            orderDetails.add(orderDetail);
        }
        orederDetailMapper.saveOrderDetails(orderDetails);

        //5.清空购物车
        shoppingCartMapper.clean(BaseContext.getCurrentId());
        //6.组装OrderSubmitVO，返回到控制层
        OrderSubmitVO orderSubmitVO = new OrderSubmitVO();
        //补全属性
        orderSubmitVO.setId(orders.getId());
        orderSubmitVO.setOrderNumber(orders.getNumber());
        orderSubmitVO.setOrderAmount(orders.getAmount());
        orderSubmitVO.setOrderTime(orders.getOrderTime());
        return orderSubmitVO;
    }

    @Override
    public PageResult historyOrders(Integer page, Integer pageSize, Integer status) {
        PageHelper.startPage(page, pageSize);
        Long userId = BaseContext.getCurrentId();
        Page<OrderVO> p = orderMapper.historyOrders(userId, status);
        if (p == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        //遍历订单列表，根据订单id查询订单详情列表
        for (OrderVO vo : p) {
            //获取每个订单的订单ID
            Long orderId = vo.getId();
            //根据订单ID查询订单详情列表
            List<OrderDetail> orderDetailList = orederDetailMapper.getOrderDetailListByOrderId(orderId);
            vo.setOrderDetailList(orderDetailList);

        }

        PageResult pageResult = new PageResult(p.getTotal(), p.getResult());

        return pageResult;
    }

    @Override
    public OrderVO getOrderDetailByOrderId(Long id) {
        OrderVO orderVO = orderMapper.getOrderDetailByOrderId(id);
        List<OrderDetail> orderDetailList = orederDetailMapper.getOrderDetailListByOrderId(id);
        orderVO.setOrderDetailList(orderDetailList);
        return orderVO;
    }

    @Override
    public void cancelOrder(Long id) {
        orderMapper.cancelOrder(id);
    }

    @Override
    public void repetition(Long id) {
        List<OrderDetail> orderDetailList = orederDetailMapper.getOrderDetailListByOrderId(id);
        for (OrderDetail orderDetail : orderDetailList) {
            ShoppingCartDTO shoppingCartDTO = new ShoppingCartDTO();
            BeanUtils.copyProperties(orderDetail, shoppingCartDTO);
            Integer number = orderDetail.getNumber();
            for (int i = 0; i < number; i++) {
                shoppingCartService.addShoppingCart(shoppingCartDTO);
            }

        }
    }

    /**
     * 订单支付
     *
     * @param dto
     * @return
     */
    @Override
    public LocalDateTime payment(OrdersPaymentDTO dto) {
        Orders orders = Orders.builder()
                .number(dto.getOrderNumber())
                .payMethod(dto.getPayMethod())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .estimatedDeliveryTime(LocalDateTime.now().plusHours(1))
                .build();
        orderMapper.payment(orders);
        //////////////////////////////////////////////
        Map map = new HashMap();
        map.put("type", 1);//消息类型，1表示来单提醒
        map.put("orderId", orders.getId());
        map.put("content", "订单号：" + dto.getOrderNumber());

        //通过WebSocket实现来单提醒，向客户端浏览器推送消息
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
        ///////////////////////////////////////////////////
        return orders.getEstimatedDeliveryTime();
    }

    /**
     * 商家端条件分页查询
     *
     * @param beginTime
     * @param endTime
     * @param number
     * @param page
     * @param pageSize
     * @param phone
     * @param status
     * @return
     */
    @Override
    public PageResult conditionSearch(LocalDate beginTime, LocalDate endTime, Integer number, Integer page, Integer pageSize, String phone, Integer status) {
        PageHelper.startPage(page, pageSize);
        Page<OrderVO> p = orderMapper.conditionSearch(beginTime, endTime, number, phone, status);
        //需要补全OrderVO的属性  orderDishes 所有菜品的字符串形式

        PageResult pageResult = new PageResult(p.getTotal(), p.getResult());
        return pageResult;
    }

    @Override
    public OrderStatisticsVO getNumberByStatus() {
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        Integer confirmed = orderMapper.getNumberByStatus(Orders.CONFIRMED);
        Integer deliveryInProgress = orderMapper.getNumberByStatus(Orders.DELIVERY_IN_PROGRESS);
        Integer toBeConfirmed = orderMapper.getNumberByStatus(Orders.TO_BE_CONFIRMED);
        orderStatisticsVO.setConfirmed(confirmed);
        orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);
        orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
        return orderStatisticsVO;
    }

    @Override
    public void confirmOrder(OrdersConfirmDTO dto) {
        dto.setStatus(Orders.CONFIRMED);
        Orders orders = new Orders();
        BeanUtils.copyProperties(dto, orders);
        orderMapper.updateOrderStatus(orders);
    }

    @Override
    public void rejectionOrder(OrdersRejectionDTO dto) {
        Orders orders = Orders.builder().id(dto.getId()).status(Orders.CANCELLED).rejectionReason(dto.getRejectionReason()).build();
        orderMapper.updateOrderStatus(orders);
    }

    @Override
    public void adminCancelOrder(OrdersCancelDTO dto) {
        Orders orders = Orders.builder()
                .id(dto.getId())
                .status(Orders.CANCELLED)
                .cancelReason(dto.getCancelReason())
                .cancelTime(LocalDateTime.now())
                .build();
        orderMapper.updateOrderStatus(orders);
    }

    @Override
    public void deliveryOrder(Long id) {
        Orders orders = Orders.builder().id(id).status(Orders.DELIVERY_IN_PROGRESS)
                .estimatedDeliveryTime(LocalDateTime.now().plusHours(1))
                .build();
        orderMapper.updateOrderStatus(orders);
    }

    @Override
    public void completeOrder(Long id) {
        Orders orders = Orders.builder().id(id).status(Orders.COMPLETED)
                .deliveryTime(LocalDateTime.now())
                .build();
        orderMapper.updateOrderStatus(orders);
    }

    @Override
    public void reminder(Long id) {
        // 查询订单是否存在
        Orders orders = orderMapper.getById(id);
        if (orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //基于WebSocket实现催单
        Map map = new HashMap();
        map.put("type", 2);//2代表用户催单
        map.put("orderId", id);
        map.put("content", "订单号：" + orders.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
    }
}
